using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace GURUCORE.Framework.Core.Data
{
	public class DTOCollection : ArrayList
	{
		public static DTOCollection FromGenericDTOCollection<T>(DTOCollection<T> p_arrSource) where T : DTOBase
		{
			DTOCollection arrResult = new DTOCollection();
			foreach (T dto in p_arrSource)
			{
				arrResult.Add(dto);
			}
			return arrResult;
		}

		public static DTOCollection<T> ToGenericDTOCollection<T>(DTOCollection p_arrSource) where T : DTOBase
		{
			DTOCollection<T> arrResult = new DTOCollection<T>();
			foreach (T dto in p_arrSource)
			{
				arrResult.Add(dto);
				arrResult.SetUnchanged(dto);
			}
			return arrResult;
		}
	}

	/// <summary>
	/// collection of DTO, implement all method like ArrayList
	/// </summary>
	[Serializable]
    [System.Diagnostics.DebuggerStepThrough()]
	public class DTOCollection<T> : IEnumerable<T> where T : DTOBase
	{
		private List<T> m_arrMain;
		private List<T> m_arrChanged;
		private List<T> m_arrAdded;
		private List<T> m_arrDeleted;

		public DTOCollection() : base()
		{
			m_arrMain = new List<T>();
			m_arrChanged = new List<T>();
			m_arrAdded = new List<T>();
			m_arrDeleted = new List<T>();
		}

		public void Fill(T p_dtoItem)
		{
			m_arrMain.Add(p_dtoItem);
		}

		public void Add(T[] p_arrItem)
		{
			foreach (T dtoItem in p_arrItem)
			{
				Add(dtoItem);
			}
		}

		public void Add(T p_dtoItem)
		{
			m_arrMain.Add(p_dtoItem);
			m_arrAdded.Add(p_dtoItem);
		}

		public void Remove(T p_dtoItem)
		{
			m_arrMain.Remove(p_dtoItem);
			if (m_arrAdded.Contains(p_dtoItem))
			{
				m_arrAdded.Remove(p_dtoItem);
			}
			
			m_arrDeleted.Add(p_dtoItem);
		}

		public void RemoveAt(int p_nIndex)
		{
			m_arrDeleted.Add(m_arrMain[p_nIndex]);
			m_arrMain.RemoveAt(p_nIndex);
		}

		public bool Contains(T p_dtoItem)
		{
			return m_arrMain.Contains(p_dtoItem);
		}

		public T this[int p_nIndex]
		{
			get
			{
				return m_arrMain[p_nIndex];
			}
			set
			{
				m_arrMain[p_nIndex] = value;
			}			
		}

		public T[] ToArray()
		{
			return m_arrMain.ToArray();
		}

		public void FromArray(T[] p_arrItem)
		{
			m_arrMain.RemoveRange(0, m_arrMain.Count);
			foreach (T dtoItem in p_arrItem)
			{
				m_arrMain.Add(dtoItem);
			}
		}

		public int Count
		{
			get
			{
				return m_arrMain.Count;
			}
		}

		public T[] ChangedList
		{
			get
			{
				return m_arrChanged.ToArray();
			}
		}

		public T[] DeletedList
		{
			get
			{
				return m_arrDeleted.ToArray();
			}
		}

		public T[] AddedList
		{
			get
			{
				return m_arrAdded.ToArray();
			}
		}

		public void SetChanged(T p_dtoItem)
		{
			if ((! m_arrChanged.Contains(p_dtoItem)) && (! m_arrAdded.Contains(p_dtoItem)))
			{
				m_arrChanged.Add(p_dtoItem);
			}			
		}

		public void Insert(int p_nIndex,T p_dtoItem)
		{
			m_arrMain.Insert(p_nIndex, p_dtoItem);
			m_arrAdded.Add(p_dtoItem);
		}

		public void SetUnchanged(T p_dtoItem)
		{
			m_arrChanged.Remove(p_dtoItem);
		}

		public IEnumerator<T> GetEnumerator()
		{
			return m_arrMain.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return m_arrMain.GetEnumerator();
		}

		public T Find(Predicate<T> p_oMatch)
		{
			return m_arrMain.Find(p_oMatch);
		}

		public void ForEach(Action<T> p_oAction)
		{
			m_arrMain.ForEach(p_oAction);
		}

		public void Sort(Comparison<T> p_oComparision)
		{
			m_arrMain.Sort(p_oComparision);
		}
	}
}
